package org.alvin.lock;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.lang.reflect.Method;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

/**
 * 泊云智能锁 平台对接客户端
 */
public class BoyunLockClient extends PropertyChangeSupport {

    private WebSocketClient webSocketClient;

    public BoyunLockClient(String url) throws Exception {
        super("");
        CountDownLatch countDownLatch = new CountDownLatch(1);
        webSocketClient = new WebSocketClient(url, countDownLatch, BoyunLockClient.this);
        webSocketClient.connect();
        initEvent();
        countDownLatch.await();
    }

    private void initEvent() {
        //连接成功，开始发心跳
        this.addPropertyChangeListener("connect", new PropertyChangeListener() {
            @Override
            public void propertyChange(PropertyChangeEvent evt) {
                System.out.println("=========================");
                new Thread() {
                    @Override
                    public void run() {
                        while (true) {
                            try {
                                TimeUnit.SECONDS.sleep(5);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                            if (webSocketClient.isConnect()) {
                                System.out.println("发送心态包");
                                heartbeat();
                            }
                        }
                    }
                }.start();
            }
        });

        this.addPropertyChangeListener("requestDataChange", new PropertyChangeListener() {
            @Override
            public void propertyChange(PropertyChangeEvent evt) {
                String msg = (String) evt.getNewValue();
                System.out.println(msg);
                JSONObject responseMsg = JSONObject.parseObject(msg);
                String state = responseMsg.getString("state");
                String methodName = "response" + state;
                Class clz = BoyunLockClient.class;
                Method method = null;
                try {
                    method = clz.getDeclaredMethod(methodName, JSONObject.class);
                } catch (NoSuchMethodException e) {
                    e.printStackTrace();
                }
                if (method != null) {
                    try {
                        method.invoke(BoyunLockClient.this, responseMsg);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                } else {
                    System.out.println("不支持的方法");
                }
            }
        });

        firePropertyChange("connect", false, true);
    }

    /**
     * 发送命令
     *
     * @param msg
     */
    private void sendData(JSONObject msg) {
        webSocketClient.getChannel().writeAndFlush(new TextWebSocketFrame(msg.toJSONString()));
    }

    /**
     * 心跳
     */
    private void heartbeat() {
        //{"command":"HeartBeat"}
        JSONObject heartbeatCmd = new JSONObject();
        heartbeatCmd.put("command", "HeartBeat");
        sendData(heartbeatCmd);
    }

    public void responseHeartBeat(JSONObject msg) {
        System.out.println("心跳回复" + msg.toJSONString());
    }

    /**
     * 升起
     */
    public void lock(String lockNum) {
        //{"command":"ControlLock","state":0,"lockNum":"12"}
        JSONObject lockCmd = new JSONObject();
        lockCmd.put("command", "ControlLock");
        lockCmd.put("state", "0");
        lockCmd.put("lockNum", lockNum);
        sendData(lockCmd);
    }

    public void responserespon(JSONObject msg) {
        //    {"state":"respon","cmd":130,"status":0}
        if (msg.getIntValue("cmd") == 130) {
            System.out.println("发送升锁命令完成");
        } else if (msg.getIntValue("cmd") == 131) {
            System.out.println("发送降锁命令完成");
        }
    }


    /**
     * 降下
     */
    public void unlock(String lockNum) {
        //{"command":"ControlLock","state":1,"lockNum":"12"}
        JSONObject unlockCmd = new JSONObject();
        unlockCmd.put("command", "ControlLock");
        unlockCmd.put("state", "1");
        unlockCmd.put("lockNum", lockNum);
        sendData(unlockCmd);
    }

    /**
     * 获取车位状态
     *
     * @param lockNum
     */
    public void parkingStatus(String lockNum) {
        //{"command":"getLockStatus","lockNum":12}
        JSONObject parkingStatusCmd = new JSONObject();
        parkingStatusCmd.put("command", "getLockStatus");
        parkingStatusCmd.put("lockNum", lockNum);
        sendData(parkingStatusCmd);
    }

    public void responsereport(JSONObject msg) {
        //{"state":"report","info":{"nslock":{"ParkId":33554444,"sLock":1},"sBits":14,"sBattery":100,"s4G":4}}
        // sLock:0：关锁（上限位）；1：开锁无车（下限位）；2：异常在上下限位间受阻；3：异常在非行程区受阻；4：关锁有车(bit2=1)；5：开锁有车(bit2=1)；
        JSONObject info = msg.getJSONObject("info");
        info = info.getJSONObject("nslock");
        int slock = info.getIntValue("sLock");
        System.out.println("锁状态：" + slock);
        responseUpStatus();
    }


    /**
     * 获取客户所有车位状态
     */
    public void parkingListStatus() {
        //{"command":"getListLockStatus"}
        JSONObject listPparkingStatusCmd = new JSONObject();
        listPparkingStatusCmd.put("command", "getListLockStatus");
        sendData(listPparkingStatusCmd);
    }


    public void responseListReport(JSONObject msg) {
        //{"state":"ListReport","data":[{"ParkId":33554445,"sLock":0},{"ParkId":33554444,"sLock":1}]}
        // sLock:0：关锁（上限位）；1：开锁无车（下限位）；2：异常在上下限位间受阻；3：异常在非行程区受阻；4：关锁有车(bit2=1)；5：开锁有车(bit2=1)；
        JSONArray dataArray = msg.getJSONArray("data");
        for (int i = 0; i < dataArray.size(); i++) {
            System.out.println(dataArray.get(0));
        }
    }


    /**
     * 主动上报车位状态的变化相应主动上报
     */
    public void responseUpStatus() {
        //{"respon":"OK"}
        JSONObject response = new JSONObject();
        response.put("respon", "OK");
        sendData(response);
    }


}
